﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DmxInterface {

	/// <summary>Main entry point to the library. Wraps the manager, creates devices and universes.</summary>
	public class Factory : IDisposable {

		int _version;
		bool _initialized = false;

		IEngine _currentEngine;

		/// <summary>Default constructor, initializes the DMX interface using the asynchronous engine.</summary>
		public Factory()
			: this(new AsynchronousEngine()) {
		}

		/// <summary>Constructor, initializes the DMX interface using a custom engine.</summary>
		/// <param name="engine"></param>
		public Factory(IEngine engine) {
			//Issue init command with device id 0
			int res = NativeMethods.IssueDmxCommand(NativeMethods.Command.Init, 0);

			if (res >= 0)
				_version = res;
			else
				throw new Exception("Initialization failure: unable to issue Init command.");

			_initialized = true;

			_currentEngine = engine;
		}

		/// <summary>Creates a new device, using the default Id 0.</summary>
		public Device CreateDevice() {
			if (!_initialized)
				throw new InvalidOperationException("DMX interface is shutdown.");

			return CreateDevice(0);
		}

		/// <summary>Creates a new device with a custom Id.</summary>
		/// <param name="id">Id of the device (from 0 to 7?).</param>
		public Device CreateDevice(int id) {
			if (!_initialized)
				throw new InvalidOperationException("DMX interface is shutdown.");

			return new Device(id);
		}

		/// <summary>Closes the DMX interface.</summary>
		public void Shutdown() {
			if (_initialized) {
				NativeMethods.IssueDmxCommand(NativeMethods.Command.Exit, 0);

				_initialized = false;
			}
		}

		/// <summary>Returns the current engine.</summary>
		public IEngine Engine {
			get {
				return _currentEngine;
			}
		}

		/// <summary>Sets a new engine, disposing the old one. All settings are lost and couplings are not kept.</summary>
		public void SetNewEngine(IEngine engine){
			_currentEngine.Dispose();

			_currentEngine = engine;
		}

		public int Version {
			get {
				return _version;
			}
		}

		#region IDisposable Members

		public void Dispose() {
			Shutdown();
		}

		#endregion
	}

}
